使用上跟MethodChannel
類似,EventChannel
即為MethodChannel
與Stream
的結合
Flutter 端:
首先同樣先建立Channel
並指定名稱(記得所有通道名稱都不能重複),然後要對Native 端傳遞來的訊息進行監聽,通過EventChannel
調用receiveBroadcastStream()
來取得一個Stream
物件,後續通過在Stream
中新增監聽來完成對 Native 端訊息的接收等操作
lib/batterylevel.dart
:
這邊建立一個EvnetChannel
來取得Native 端一個骰子持續搖出來的數字,並建立一個取得骰子訊息的Stream
物件方法
static const EventChannel _eventChannel = const EventChannel('dice_number');
static Stream<int> get getRandomNumberStream {
return _eventChannel.receiveBroadcastStream().cast();
}
Native 端(Android):
android/.../BatterylevelPlugin.kt
:
這邊一樣要設置好EvnetChannel
,指定名稱(需要與Flutter 端使用的EvnetChannel
名稱相對應),並通過EvnetChannel
呼叫setStreamHandler
來註冊一個MessageHandler
來接收此通道訊息,這邊不像預設的範例直接讓BatterylevelPlugin
實現setStreamHandler
的接口,我們將接口的實現拉出來一個類別來實作,這樣把實現接口的邏輯拉出去實作,BatterylevelPlugin
才不會在功能變多時變得太複雜
所以建立一個RandomNumberStreamHandler.kt
來實現接口,這邊每一秒骰一次骰子並將結果回傳至Flutter 端
class RandomNumberStreamHandler : EventChannel.StreamHandler {
private var sink: EventChannel.EventSink? = null
private var handler: Handler? = null
private val runnable = Runnable {
sendNewRandomNumber()
}
private fun sendNewRandomNumber() {
val randomNumber = (1..6).random()
sink?.success(randomNumber)
handler?.postDelayed(runnable, 1000)
}
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
sink = events
handler = Handler()
handler?.post(runnable)
}
override fun onCancel(arguments: Any?) {
sink = null
handler?.removeCallbacks(runnable)
}
}
BatterylevelPlugin.kt
加上:
private lateinit var eventChannel: EventChannel
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
//Added
eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, "dice_number")
eventChannel.setStreamHandler(RandomNumberStreamHandler())
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
//Added
eventChannel.setStreamHandler(null)
}
Native 端(iOS):
一樣可以把setStreamHandler
的接口實現的邏輯拉出去實作,同樣建立一個RandomNumberStreamHandler.swift
來實現接口,每一秒骰一次骰子並將結果回傳至Flutter 端
ios/Classes/RandomNumberStreamHandler.swift
import Foundation
import Flutter
class RandomNumberStreamHandler: NSObject, FlutterStreamHandler{
var sink: FlutterEventSink?
var timer: Timer?
@objc func sendNewRandomNumber() {
guard let sink = sink else { return }
let randomNumber = Int.random(in: 1..<7)
sink(randomNumber)
}
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
sink = events
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(sendNewRandomNumber), userInfo: nil, repeats: true)
return nil
}
func onCancel(withArguments arguments: Any?) -> FlutterError? {
sink = nil
timer?.invalidate()
return nil
}
}
ios/Classes/SwiftBatterylevelPlugin.swift
:
import Flutter
import UIKit
public class SwiftBatterylevelPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
//Added
let eventChannel = FlutterEventChannel(name: "dice_number", binaryMessenger: registrar.messenger())
let randomNumberStreamHandler = RandomNumberStreamHandler()
eventChannel.setStreamHandler(randomNumberStreamHandler)
}
}